package io.keen.client.android;

import android.os.Build.VERSION;
import io.keen.client.java.KeenJsonHandler;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class AndroidJsonHandler implements KeenJsonHandler {
    private boolean isWrapNestedMapsAndCollections;

    public AndroidJsonHandler() {
        this.isWrapNestedMapsAndCollections = VERSION.SDK_INT < 19;
    }

    public Map<String, Object> readJson(Reader reader) throws IOException {
        if (reader == null) {
            throw new IllegalArgumentException("Reader must not be null");
        }
        try {
            return JsonHelper.toMap(new JSONObject(readerToString(reader)));
        } catch (JSONException e) {
            throw new IOException(e);
        }
    }

    public void writeJson(Writer writer, Map<String, ?> value) throws IOException {
        if (writer == null) {
            throw new IllegalArgumentException("Writer must not be null");
        }
        writer.write(convertMapToJSONObject(value).toString());
        writer.close();
    }

    private JSONObject convertMapToJSONObject(Map map) throws IOException {
        Map newMap;
        if (this.isWrapNestedMapsAndCollections && requiresWrap(map)) {
            newMap = new HashMap();
            for (Object key : map.keySet()) {
                Object value = map.get(key);
                Object newValue = value;
                if (value instanceof Map) {
                    newValue = convertMapToJSONObject((Map) value);
                } else if (value instanceof Collection) {
                    newValue = convertCollectionToJSONArray((Collection) value);
                }
                newMap.put(key, newValue);
            }
        } else {
            newMap = map;
        }
        return new JSONObject(newMap);
    }

    private JSONArray convertCollectionToJSONArray(Collection collection) throws IOException {
        Collection newCollection;
        if (this.isWrapNestedMapsAndCollections && requiresWrap(collection)) {
            newCollection = new ArrayList();
            for (Object value : collection) {
                Object newValue = value;
                if (value instanceof Map) {
                    newValue = convertMapToJSONObject((Map) value);
                } else if (value instanceof Collection) {
                    newValue = convertCollectionToJSONArray((Collection) value);
                }
                newCollection.add(newValue);
            }
        } else {
            newCollection = collection;
        }
        return new JSONArray(newCollection);
    }

    private static String readerToString(Reader reader) throws IOException {
        StringWriter writer = new StringWriter();
        try {
            char[] buffer = new char[4096];
            while (true) {
                int bytesRead = reader.read(buffer);
                if (bytesRead == -1) {
                    break;
                }
                writer.write(buffer, 0, bytesRead);
            }
            String stringWriter = writer.toString();
            return stringWriter;
        } finally {
            reader.close();
        }
    }

    private static boolean requiresWrap(Map map) {
        for (Object value : map.values()) {
            if (!(value instanceof Collection)) {
                if (value instanceof Map) {
                }
            }
            return true;
        }
        return false;
    }

    private static boolean requiresWrap(Collection collection) {
        for (Object value : collection) {
            if (!(value instanceof Collection)) {
                if (value instanceof Map) {
                }
            }
            return true;
        }
        return false;
    }
}
